package com.jj.test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.GeneratedMessageV3;
import com.jj.battle.protocol.GameProto;
import com.jj.battle.protocol.ProtocolId;
import com.jj.core.client.impl.ClientManagerImpl;
import com.jj.core.client.sim.ClientSim;
import com.jj.message.PBMessageFactory;
import com.jj.message.ProtoFormat;
import com.jj.message.Result;
import com.jj.message.battle.UserMessage;
import com.jj.net.kcp.KcpState;
import com.jj.protocol.LogonResponse;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.util.ResourceLeakDetector;
import org.beykery.jkcp.KcpClient;
import org.beykery.jkcp.KcpOnUdp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * Copyrights: QidianGroup@JJ
 *
 * @author: LuHan
 * @date: 2018/1/15, 14:56
 */
public class ClientTester extends KcpClient {
    private static Logger logger = LoggerFactory.getLogger(ClientTester.class);

    public static final String host = "127.0.0.1";
    public static final int port = 9001;

    private static ClientManagerImpl clientManager = new ClientManagerImpl();

    private static PBMessageFactory pbMessageFactory = new PBMessageFactory();

    static{
        pbMessageFactory.init();
    }

    private ClientSim tcpClient = null;

    {
        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);

        noDelay(1, 20, 2, 1);
        setMinRto(10);
        wndSize(32, 32);
        setTimeout(10 * 1000);
        setMtu(1400);
    }

    public void setCnv(int conv){
        setConv(conv);
    }

    public ClientSim getTcpClient() {
        return tcpClient;
    }

    public boolean connectTcp(String host, int port){
        tcpClient = new ClientSim(host, port);
        return tcpClient.connect();
    }

    public void connectKcp(String host, int port){
        connect(new InetSocketAddress(host, port));
        start();
    }

    public void sendKcp(UserMessage userMsg){
        ByteBuf bb = PooledByteBufAllocator.DEFAULT.buffer(1500);
        userMsg.write2ByteBuf(bb);
        send(bb);
    }

    public static void main(String[] args) throws InterruptedException {
        ClientTester tester = new ClientTester();

        if (tester.connectTcp(host, port)) {
            //send some json message
            {
                UserMessage ioMsg = null;
                Map<String, String> logonReq = new HashMap<>();
                logonReq.put("guid", "dfc1eb68-9a28-43ea-bdfb-7ed4828e8e9b");
                logonReq.put("version", "1.0.0");
                logonReq.put("firstLogon", "true");

                tester.getTcpClient().send(1, JSON.toJSONString(logonReq));
                UserMessage resp = tester.getTcpClient().read();
                String jsonStr = resp.getJsonMsg();
                JSONObject jsonObj = JSON.parseObject(jsonStr);
                logger.debug("response:{},{}", resp.getMsgID(), jsonObj);

//                JSONObject value = jsonObj.getJSONObject("value");
//                KcpState kcpState = value.getObject("kcpState", KcpState.class);
//
//                tester.setCnv(kcpState.conv);
//                tester.connectKcp(kcpState.host, kcpState.port);


                tester.getTcpClient().send(9, "{\"characterId\":999}");
                resp = tester.getTcpClient().read();

                //send join
                tester.getTcpClient().send(7, "");
                resp = tester.getTcpClient().read();
                logger.debug("jion response:{}", resp);


                int frameNum = 1;
                while(true) {
                    UserMessage cmd = new UserMessage();
                    GameProto.PKG_OPERATION.Builder builder = GameProto.PKG_OPERATION.newBuilder();
//                    builder.setOperation(999);
//                    builder.setFrameNo(frameNum++);
                    cmd.setProtocolFormat(ProtoFormat.ProtoBuf);
                    cmd.setMsgID((short) ProtocolId.ProtoId.MSG_OPERATION_VALUE);
                    cmd.setPayload(pbMessageFactory.serialize(builder.build()));
                    tester.sendKcp(cmd);
                    Thread.sleep(1000);
                }
            }
        }
    }

    public static void dumpMsg(UserMessage ioMessage){
        String payload = null;
        switch (ioMessage.getProtocolFormat()){
            case JSON:
            case Request:
            case Response:
                payload = new String(ioMessage.getPayload());
                break;
            case Standard:
                payload = "STANDARD";
                break;
            default:
                break;
        }
        logger.debug("id:{}, protocol:{}, requestId:{}, payload:{}",
                ioMessage.getMsgID(),
                ioMessage.getProtocolFormat(),
                ioMessage.getRequestId(),
                payload);
    }

    @Override
    public void handleReceive(ByteBuf bb, KcpOnUdp kcp)
    {
        UserMessage userMessage = UserMessage.parseFrom(bb);
        GeneratedMessageV3 pbMsg = pbMessageFactory.build(userMessage.getMsgID(), userMessage.getPayload());
        logger.debug("rcv:{}", pbMsg);
        //String content = bb.toString(Charset.forName("utf-8"));
        //System.out.println("conv:" + kcp.getKcp().getConv() + " recv:" + content + " kcp-->" + kcp);

    }

    /**
     * kcp异常，之后此kcp就会被关闭
     *
     * @param ex
     * @param kcp
     */
    @Override
    public void handleException(Throwable ex, KcpOnUdp kcp)
    {
        System.out.println(ex);
    }

    @Override
    public void handleClose(KcpOnUdp kcp)
    {
        super.handleClose(kcp);
        System.out.println("服务器离开:" + kcp);
        System.out.println("waitSnd:" + kcp.getKcp().waitSnd());
    }
}
